<template>
	<div class="outer" :style="{ backgroundColor: outerBgColor, transition: 'background-color 0.5s' }" ref="outContainer">
		<div class="title">ffffeliks</div>
		<div class="mask" ref="maskRef" @click="closeMask"></div>
		<div class="circleContainer" ref="circleContainer" :style="circleStyle">
			<div
				class="card"
				v-for="(card, index) in cards"
				:key="index"
				:style="[getCardStyle(index, cards.length), { transform: cardRotationStyles[index] }]"
				:class="{ topCard: isTopCard(index) }"
				:ref="setCardRef(index)"
				@click="showDetail(card, index)"
			>
				<div class="head" v-if="card.title">
					<div class="h-small-title">{{ card.outTitle }}</div>
					<div class="h-large-title">{{ card.title }}</div>
				</div>
				<div class="foot" v-if="card.title">
					<div class="f-large-title">{{ card.id }}</div>
					<div class="f-small-title">{{ card.desc }}</div>
				</div>
				<div class="empty-content" v-if="!card.title">
					<div v-for="i in 3" :key="i" class="ball"></div>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
import {ref, computed, onMounted, onUnmounted} from 'vue';
import {useStore} from 'vuex';
import anime from 'animejs/lib/anime.es.js';
import {getRandomColor} from '@/utils/randomColor';
import cardsJson from '@/utils/cards.json';
import {useRouter} from 'vue-router';

const store = useStore();
const router = useRouter();

const circleSize = ref(110);
const cardWidth = ref(16);
const cardHeight = ref(11);
const circleContainer = ref(null);
const cardRefs = ref([]);
const maskRef = ref(null);
// const outerContainer = ref(null);

const currentAngle = ref(store.state.currentAngle);
const topCardIndex = ref(store.state.topCardIndex);
const cards = ref(store.state.cards.length ? store.state.cards : cardsJson.map(card => ({...card, color: card.bgColor || getRandomColor()})));
const outerBgColor = ref(store.state.outerBgColor);

const circleStyle = computed(() => ({
	width: `${circleSize.value}vw`,
	height: `${circleSize.value}vw`,
	borderWidth: '1px',
}));

const setCardRef = (index) => (el) => {
	cardRefs.value[index] = el;
};

const getCardStyle = (index, total) => {
	const angle = (index / total) * 360;
	const radius = (circleSize.value / 2) - 0.5;
	const x = radius * Math.cos((angle * Math.PI) / 180);
	const y = radius * Math.sin((angle * Math.PI) / 180);
	const cardCenterX = x + circleSize.value / 2;
	const cardCenterY = y + circleSize.value / 2;
	return {
		width: `${cardWidth.value}vw`,
		height: `${cardHeight.value}vw`,
		top: `calc(${cardCenterY}vw - ${cardHeight.value / 2}vw)`,
		left: `calc(${cardCenterX}vw - ${cardWidth.value / 2}vw)`,
		transformOrigin: 'center',
		backgroundColor: cards.value[index].color,
	};
};

const cardRotationStyles = computed(() => {
	return cards.value.map((_, index) => {
		const angle = (index / cards.value.length) * 360;
		const adjustedAngle = (angle) % 360;
		return isTopCard(index) ? `rotate(${adjustedAngle}deg) scale(1.2)` : `rotate(${adjustedAngle}deg)`;
	});
});

const isTopCard = (index) => {
	const angle = (index / cards.value.length) * 360;
	const adjustedAngle = (angle + currentAngle.value) % 360;
	return Math.abs(adjustedAngle + 90) < 5;
};

let startAngle = 0;
let isDragging = false;

const startDrag = (event) => {
	startAngle = getAngle(event);
	isDragging = true;
	window.addEventListener('mousemove', onDrag);
	window.addEventListener('mouseup', stopDrag);
	window.addEventListener('touchmove', onDrag);
	window.addEventListener('touchend', stopDrag);
};

const onDrag = (event) => {
	if (!isDragging) return;
	const angle = getAngle(event);
	const delta = angle - startAngle;
	currentAngle.value += delta;
	startAngle = angle;
	updateRotation();
};

const stopDrag = () => {
	isDragging = false;
	window.removeEventListener('mousemove', onDrag);
	window.removeEventListener('mouseup', stopDrag);
	window.removeEventListener('touchmove', onDrag);
	window.removeEventListener('touchend', stopDrag);
	slowStopRotation();
};

const updateRotation = () => {
	anime({
		targets: circleContainer.value,
		rotate: `${currentAngle.value}deg`,
		duration: 100,
		easing: 'easeOutElastic(1, .8)',
		update: () => {
			cards.value.forEach((_, index) => {
				const angle = (index / cards.value.length) * 360;
				if (isTopCard(index)) {
					topCardIndex.value = index;
					document.querySelectorAll('.card')[index].classList.add('topCard');
					document.querySelectorAll('.card')[index].style.transform = `rotate(${angle}deg) scale(1.2)`;
				} else {
					document.querySelectorAll('.card')[index].classList.remove('topCard');
					document.querySelectorAll('.card')[index].style.transform = `rotate(${angle}deg)`;
				}
			});
		}
	});
};

const slowStopRotation = () => {
	const additionalAngle = 0;
	anime({
		targets: circleContainer.value,
		rotate: `${currentAngle.value + additionalAngle}deg`,
		duration: 300,
		easing: 'easeOutElastic(1, .8)',
		update: () => {
			cards.value.forEach((_, index) => {
				const angle = (index / cards.value.length) * 360;
				if (isTopCard(index)) {
					document.querySelectorAll('.card')[index].classList.add('topCard');
					document.querySelectorAll('.card')[index].style.transform = `rotate(${angle}deg) scale(1.2)`;
				} else {
					document.querySelectorAll('.card')[index].classList.remove('topCard');
					document.querySelectorAll('.card')[index].style.transform = `rotate(${angle}deg)`;
				}
			});
		}
	});
};

const getAngle = (event) => {
	const rect = circleContainer.value.getBoundingClientRect();
	const clientX = event.clientX || event.touches[0].clientX;
	const clientY = event.clientY || event.touches[0].clientY;
	const x = clientX - (rect.left + rect.width / 2);
	const y = clientY - (rect.top + rect.height / 2);
	return Math.atan2(y, x) * (180 / Math.PI);
};

const showDetail = (card, index) => {
	store.commit('setOuterBgColor', card.color);
	store.commit('setCurrentAngle', currentAngle.value);
	store.commit('setTopCardIndex', topCardIndex.value);
	store.commit('setCards', cards.value);
	
	if (index === topCardIndex.value) {
		anime({
			targets: cardRefs.value[index],
			translateX: '20vh',
			duration: 500,
			easing: 'easeOutElastic(1, .6)',
			complete: () => {
				router.push({name: card.to});
			}
		});
	}
};

const closeMask = () => {
	maskRef.value.style.transform = 'translateX(-100vw)';
};

onMounted(() => {
	window.addEventListener('mousedown', startDrag);
	window.addEventListener('touchstart', startDrag);
	window.addEventListener('mousemove', onDrag);
	window.addEventListener('touchmove', onDrag);
	window.addEventListener('mouseup', stopDrag);
	window.addEventListener('touchend', stopDrag);
	updateRotation();
});

onUnmounted(() => {
	window.removeEventListener('mousedown', startDrag);
	window.removeEventListener('touchstart', startDrag);
	window.removeEventListener('mousemove', onDrag);
	window.removeEventListener('touchmove', onDrag);
	window.removeEventListener('mouseup', stopDrag);
	window.removeEventListener('touchend', stopDrag);
});
</script>

<style scoped lang="scss">
@import "./emptyCard.scss";

.outer {
	width: 100vw;
	height: 100vh;
	position: absolute;
	top: 0;
	left: 0;
	overflow: hidden;
	cursor: grab;
	
	&:active {
		cursor: grabbing;
	}
	
	.title {
		margin: 48px auto;
		font-size: 2.5rem;
		font-style: italic;
		font-family: fantasy;
		//不可选中
		user-select: none;
		mix-blend-mode: difference;
		color: red;
		text-align: center;
	}
	
	.mask {
		position: absolute;
		width: 100vw;
		height: 100vh;
		left: 0;
		top: 0;
		z-index: 98;
		transform: translateX(-100vw);
		transition: all 1s;
	}
}

.circleContainer {
	position: absolute;
	//border: 2px solid black;
	border-radius: 50%;
	left: -5vw;
	bottom: -90vw;
}

.card {
	position: absolute;
	transform-origin: center;
	border-radius: 10px;
	box-shadow: -2px -2px 10px #000;
	transition: transform 0.3s ease; // 加入平滑过渡效果
	
	display: flex;
	flex-direction: row-reverse;
	justify-content: space-between;
	color: #fff;
	padding-top: 10px;
	padding-left: 10px;
	//竖直排列文字
	.head, .foot {
		transform: rotate(90deg);
		mix-blend-mode: soft-light;
		text-shadow: -2px 2px 4px rgba(0, 0, 0, 1);
		user-select: none;
	}
	
	.head {
		display: grid;
		align-content: stretch;
		align-items: stretch;
		
		.h-small-title {
			font-size: 1vw;
			transform: rotate(-90deg);
		}
		
		.h-large-title {
			font-size: 1.5vw;
			font-family: fantasy;
		}
	}
	
	.foot {
		width: 18vw;
		display: flex;
		justify-content: space-between;
		align-items: end;
		
		.f-large-title {
			font-size: 3vw;
			font-family: fantasy;
		}
		
		.f-small-title {
			font-size: 4vw;
			font-weight: bold;
			font-family: cursive;
			position: absolute;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%) scale(1.5);
		}
	}
}

.topCard {
	z-index: 99; /* 确保顶层 */
}
</style>
